package org.example.xsda.service;

import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.example.xsda.common.PageResult;
import org.example.xsda.entity.Message;
import org.example.xsda.entity.SysUser;
import org.example.xsda.mapper.MessageMapper;
import org.example.xsda.mapper.SysUserMapper;
import org.example.xsda.vo.MessageVO;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Service
public class MessageService {
    
    @Resource
    private MessageMapper messageMapper;
    
    @Resource
    private SysUserMapper userMapper;
    
    @Resource
    private RedisService redisService;
    
    // 缓存key前缀
    private static final String CACHE_KEY_UNREAD_COUNT = "message:unread:";
    private static final String CACHE_KEY_STATISTICS = "message:stats:";
    
    public PageResult<MessageVO> getMessagePage(Integer current, Integer size, String type) {
        Long userId = StpUtil.getLoginIdAsLong();
        
        Page<Message> page = new Page<>(current, size);
        
        LambdaQueryWrapper<Message> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Message::getUserId, userId);
        wrapper.eq(type != null && !type.isEmpty(), Message::getType, type);
        wrapper.orderByDesc(Message::getCreateTime);
        
        IPage<Message> messagePage = messageMapper.selectPage(page, wrapper);
        
        List<MessageVO> voList = new ArrayList<>();
        for (Message message : messagePage.getRecords()) {
            MessageVO vo = new MessageVO();
            BeanUtils.copyProperties(message, vo);
            voList.add(vo);
        }
        
        return new PageResult<>(messagePage.getTotal(), voList);
    }
    
    public void markAsRead(Long id) {
        Long userId = StpUtil.getLoginIdAsLong();
        
        Message message = messageMapper.selectById(id);
        if (message == null || !message.getUserId().equals(userId)) {
            throw new RuntimeException("消息不存在");
        }
        
        message.setIsRead(1);
        messageMapper.updateById(message);
        
        // 清除缓存
        clearMessageCache(userId);
    }
    
    public void markAllAsRead() {
        Long userId = StpUtil.getLoginIdAsLong();
        
        LambdaUpdateWrapper<Message> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(Message::getUserId, userId);
        wrapper.eq(Message::getIsRead, 0);
        wrapper.set(Message::getIsRead, 1);
        
        messageMapper.update(null, wrapper);
        
        // 清除缓存
        clearMessageCache(userId);
    }
    
    public void deleteMessage(Long id) {
        Long userId = StpUtil.getLoginIdAsLong();
        
        Message message = messageMapper.selectById(id);
        if (message == null || !message.getUserId().equals(userId)) {
            throw new RuntimeException("消息不存在");
        }
        
        messageMapper.deleteById(id);
    }
    
    public Long getUnreadCount() {
        log.info("开始获取未读消息数");
        Long userId = StpUtil.getLoginIdAsLong();
        log.info("当前用户ID：{}", userId);
        String cacheKey = CACHE_KEY_UNREAD_COUNT + userId;
        
        try {
            // 先从缓存中获取
            Object cached = redisService.get(cacheKey);
            if (cached != null) {
                log.debug("从缓存中获取未读消息数：userId={}", userId);
                // 处理不同类型的返回值
                if (cached instanceof Long) {
                    return (Long) cached;
                } else if (cached instanceof Integer) {
                    return ((Integer) cached).longValue();
                } else {
                    return Long.parseLong(cached.toString());
                }
            }
        } catch (Exception e) {
            log.warn("获取未读消息缓存失败，直接查询数据库：{}", e.getMessage());
        }
        
        // 缓存未命中，从数据库查询
        log.info("从数据库查询未读消息数");
        LambdaQueryWrapper<Message> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Message::getUserId, userId);
        wrapper.eq(Message::getIsRead, 0);
        Long count = messageMapper.selectCount(wrapper);
        log.info("查询到未读消息数：{}", count);
        
        // 存入缓存（1分钟，消息数据变化频繁）
        try {
            redisService.set(cacheKey, count, 1, java.util.concurrent.TimeUnit.MINUTES);
            log.info("将未读消息数存入缓存：userId={}, count={}", userId, count);
        } catch (Exception e) {
            log.error("缓存未读消息数失败", e);
        }
        
        log.info("返回未读消息数：{}", count);
        return count;
    }
    
    @SuppressWarnings("unchecked")
    public Map<String, Long> getStatistics() {
        Long userId = StpUtil.getLoginIdAsLong();
        String cacheKey = CACHE_KEY_STATISTICS + userId;
        
        try {
            // 先从缓存中获取
            Object cached = redisService.get(cacheKey);
            if (cached != null) {
                log.debug("从缓存中获取消息统计：userId={}", userId);
                return (Map<String, Long>) cached;
            }
        } catch (Exception e) {
            log.warn("获取消息统计缓存失败，直接查询数据库：{}", e.getMessage());
        }
        
        // 缓存未命中，从数据库查询
        Map<String, Long> stats = new HashMap<>();
        
        LambdaQueryWrapper<Message> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Message::getUserId, userId);
        
        stats.put("totalCount", messageMapper.selectCount(wrapper));
        
        wrapper.eq(Message::getIsRead, 0);
        stats.put("unreadCount", messageMapper.selectCount(wrapper));
        
        wrapper.clear();
        wrapper.eq(Message::getUserId, userId);
        wrapper.eq(Message::getType, "approval");
        wrapper.eq(Message::getIsRead, 0);
        stats.put("approvalCount", messageMapper.selectCount(wrapper));
        
        wrapper.clear();
        wrapper.eq(Message::getUserId, userId);
        wrapper.eq(Message::getType, "notice");
        wrapper.eq(Message::getIsRead, 0);
        stats.put("noticeCount", messageMapper.selectCount(wrapper));
        
        wrapper.clear();
        wrapper.eq(Message::getUserId, userId);
        wrapper.eq(Message::getType, "score");
        wrapper.eq(Message::getIsRead, 0);
        stats.put("scoreCount", messageMapper.selectCount(wrapper));
        
        // 存入缓存（1分钟）
        try {
            redisService.set(cacheKey, stats, 1, java.util.concurrent.TimeUnit.MINUTES);
            log.debug("将消息统计存入缓存：userId={}", userId);
        } catch (Exception e) {
            log.warn("缓存消息统计失败：{}", e.getMessage());
        }
        
        return stats;
    }
    
    public void sendMessage(Long userId, String type, String title, String content, Long relatedId) {
        Message message = new Message();
        message.setUserId(userId);
        message.setType(type);
        message.setTitle(title);
        message.setContent(content);
        message.setIsRead(0);
        message.setRelatedId(relatedId);
        
        messageMapper.insert(message);
        
        // 清除该用户的消息缓存
        clearMessageCache(userId);
    }
    
    /**
     * 清除消息相关缓存
     */
    private void clearMessageCache(Long userId) {
        redisService.delete(CACHE_KEY_UNREAD_COUNT + userId);
        redisService.delete(CACHE_KEY_STATISTICS + userId);
        log.debug("清除消息缓存：userId={}", userId);
    }
    
    /**
     * 发送消息给指定角色的所有用户
     */
    public void sendMessageToRole(String roleCode, String type, String title, String content, Long relatedId) {
        // 查询该角色的所有用户
        // 注意：这里需要通过role表关联查询，暂时使用简单实现
        // 实际应该是: SELECT user_id FROM sys_user WHERE role_id IN (SELECT id FROM sys_role WHERE role_code = ?)
        List<SysUser> users = userMapper.selectList(null);
        
        int sendCount = 0;
        for (SysUser user : users) {
            // 检查用户角色（这里假设roleId对应roleCode，实际应该关联查询）
            if ("admin".equals(roleCode) && user.getRoleId() == 1) {
                sendMessage(user.getId(), type, title, content, relatedId);
                sendCount++;
            } else if ("teacher".equals(roleCode) && user.getRoleId() == 2) {
                sendMessage(user.getId(), type, title, content, relatedId);
                sendCount++;
            }
        }
        
        log.info("发送消息给角色[{}]的用户，共发送{}条", roleCode, sendCount);
    }
}

